class ICGen():
	def __init__(self):
		self.filename = 'inter.3d'
		self.fd = open(self.filename,'w')
		self.tempIdx = 0
		self.labelIdx = 0
		self.code = []
		self.loc = self.code
		self.ifstack = []
		self.forstack = []
		self.storedLoc = []

	def emitLabel(self,label):
		self.loc.append("%s:\n"%label)

	def emitGoto(self,label):
		label = label.replace(".","_")
		label = 'ETI'+str(label)
		sentence = "GOTO %s\n"%label
		self.loc.append(sentence)

	def emitAssignment(self,temporal,value):
		sentence = "%s := %s\n"%(temporal,value)
		self.loc.append(sentence)

	def emitIndirectAssignment(self,temporal,value):
		sentence = "%s := %s\n"%(temporal,value)
		self.loc.append(sentence)

	def emitAddition(self,param1,param2):
		return self.emitArithmeticOperation(param1,param2,'+')

	def emitSubstraction(self,param1,param2):
		return self.emitArithmeticOperation(param1,param2,'-')

	def emitMultiplication(self,param1,param2):
		return self.emitArithmeticOperation(param1,param2,'*')
	
	def emitArithmeticOperation(self,param1,param2,operator):
		temporal = self.newTemp()
		sentence = "%s := %s %s %s\n"%(temporal,param1,operator,param2)
		self.loc.append(sentence)
		return temporal

	def emitEquals(self,param1,param2):
		return self.emitRelationalOperation(param1,param2,'=')

	def emitLessThan(self,param1,param2):
		return self.emitRelationalOperation(param1,param2,'<')

	def emitAnd(self,param1,param2):
		temporal = self.newTemp()
		labelIdx = self.getLabelIdx()

		# if true param1
		sentence = "IF %s != 0 "%(param1)
		self.loc.append(sentence)
		self.emitGoto("param1True_%d"%labelIdx)
		# else
		sentence = "%s := 0\n"%temporal
		self.loc.append(sentence)
		self.emitGoto("AND_FIN%d"%labelIdx) # goto ETItemporalFIN
		# if true param2
		self.emitLabel("ETIparam1True_%d"%labelIdx)
		sentence = "IF %s != 0 "%(param2)
		self.loc.append(sentence)
		self.emitGoto("param2True_%d"%labelIdx)
		# else
		sentence = "%s := 0\n"%temporal
		self.loc.append(sentence)
		self.emitGoto("AND_FIN%d"%labelIdx) # goto ETItemporalFIN
		self.emitLabel("ETIparam2True_%d"%labelIdx)
		sentence = "%s := 1\n"%temporal
		self.loc.append(sentence)

		self.emitLabel("ETIAND_FIN%d"%labelIdx)
		return temporal



	def emitRelationalOperation(self,param1,param2,operator):
		temporal = self.newTemp()
		sentence = "IF %s %s %s "%(param1,operator,param2)
		self.loc.append(sentence)
		self.emitGoto(temporal) # goto ETItemporal
		sentence = "%s := 0\n"%temporal
		self.loc.append(sentence)
		self.emitGoto(temporal+"FIN") # goto ETItemporalFIN
		sentence = "%s:\n"%('ETI'+temporal.replace(".","_"))
		self.loc.append(sentence)
		sentence = "%s := 1\n"%temporal
		self.loc.append(sentence)
		sentence = "%s:\n"%("ETI"+temporal.replace(".","_")+"FIN")
		self.loc.append(sentence)
		return temporal


	def emitMinus(self,param1):
		temporal = self.newTemp()
		sentence = "%s := - %s\n"%(temporal,param1)
		self.loc.append(sentence)
		return temporal

	def emitString(self,string):
		temporal = self.newTemp()
		sentence = "%s := '%s'\n"%(temporal,string)
		self.loc.append(sentence)
		return temporal


	def emitNumber(self,param1):
		temporal = self.newTemp()
		sentence = "%s := %d\n"%(temporal,param1)
		self.loc.append(sentence)
		return temporal


	def emitTrue(self):
		temporal = self.newTemp()
		sentence = "%s := 1\n"%temporal
		self.loc.append(sentence)
		return temporal

	def emitFalse(self):
		temporal = self.newTemp()
		sentence = "%s := 0\n"%temporal
		self.loc.append(sentence)
		return temporal

	def emitParam(self,param):
		sentence = "PARAM %s\n"%param
		self.loc.append(sentence)

	def emitCall(self,lexeme,nParams,returnType):
		temporal = None

		if returnType != None:
			temporal = self.newTemp()
			sentence = "%s := CALL %s,%d\n"%(temporal,lexeme,nParams)
		else:
			
			sentence = "CALL %s,%d\n"%(lexeme,nParams)

		self.loc.append(sentence)

		return temporal

	def emitNewCall(self,lexeme,nParams,returnType):

		temporal = self.newTemp()
		sentence = "%s := NEW CALL %s,%d\n"%(temporal,lexeme,nParams)

		self.loc.append(sentence)

		return temporal

	def emitIf(self,condition,ifType):
		#	IF condition.post = 1 goto IFTRUE1
		#	goto ENDIF1
		#IFTRUE1:
		#	stm
		#ENDIF1:
		#

		sentence = ""

		labelIdx = self.getLabelIdx()
		
		if (ifType == "boolean"):
			sentence = "IF %s = 1 GOTO IFTRUE%d\nGOTO ENDIF%d\nIFTRUE%d:\n"%(condition,labelIdx,labelIdx,labelIdx) # if condition
		else:
		#integer . 0 : false, != 0 : true
			
			sentence = "IF %s != 0 GOTO IFTRUE%d\nGOTO ENDIF%d\nIFTRUE%d:\n"%(condition,labelIdx,labelIdx,labelIdx) # if condition

		self.ifstack.append(labelIdx)

		self.loc.append(sentence)
		
	
	def emitEndIf(self):
		currentIfIdx = self.ifstack.pop()
		endSentence = "ENDIF%d:\n"%currentIfIdx

		self.loc.append(endSentence)

#	TERNARY OPERATOR
#	IF condition.post = 1 goto IFTRUE1
		#	elseStm
		#	goto ENDIF1
		#IFTRUE1:
		#	ifStm
		#ENDIF1:
		#

	def emitTerOpCond(self,condition):

		labelIdx = self.getLabelIdx()
		self.ifstack.append(labelIdx)

		sentence = "IF %s = 0 GOTO IFFALSE%d\n "%(condition,labelIdx) # if condicion

		self.loc.append(sentence)
		temporal = self.newTemp()
		return temporal

	def emitTerOpIf(self):
		currentIfIdx = self.ifstack[-1]
		sentence = "GOTO ENDIF%d\nIFFALSE%d:\n"%(currentIfIdx,currentIfIdx) # if condicion

		self.loc.append(sentence)
		
	def emitTerOpElse(self):
		currentIfIdx = self.ifstack.pop()
		sentence = "ENDIF%d:\n"%(currentIfIdx) # if condicion

		self.loc.append(sentence)

	def emitReturn(self,lexeme):
		sentence = "RETURN %s\n"%lexeme
		self.loc.append(sentence)

	def emitForBegin(self):
		forIdx = self.getLabelIdx()
		self.forstack.append(forIdx)
		sentence = "BEGIN_FOR_IDX%d:\n"%forIdx
		self.loc.append(sentence)

	def emitForCond(self,cond):

		forIdx = self.forstack[-1]
		sentence = "COND_FOR_IDX%d:\n"%forIdx
		self.loc.append(sentence)
		sentence = "IF %s = 0 GOTO END_LOOP%d\n"%(cond,forIdx)
		self.loc.append(sentence)
		
		# update sentence must be stored because cannot be writen before sentences between braces
		self.storedLoc.append(self.loc)
		self.loc = []

	def prepareForUpdate(self):
		locBk = self.storedLoc.pop()
		self.storedLoc.append(self.loc)
		self.loc = locBk
	
	def emitForEnd(self):
		forIdx = self.forstack.pop()
		sentence = "UPDATE_LOOP%d:\n"%forIdx
		self.loc.append(sentence)
		updateSentences = self.storedLoc.pop()

		for sentence in updateSentences:
			self.loc.append(sentence)

		sentence = "GOTO BEGIN_FOR_IDX%d:\n"%forIdx
		self.loc.append(sentence)
		sentence = "END_LOOP%d:\n"%forIdx
		self.loc.append(sentence)


	def emitPrint(self,pos):
		sentence = "PRINT %s\n"%pos
		self.loc.append(sentence)

	def emitRead(self,post):
		sentence = "READ %s\n"%post
		self.loc.append(sentence)

	def getLabelIdx(self):
		current = self.labelIdx
		self.labelIdx += 1
		return current

	def writeToFile(self):
		for line in self.loc:
			try:
				self.fd.write(line)
			except Exception,e:
				#TODO define exception and raise SyntaxError if so
				print e
		self.loc = [] #reset the lines of code

	def finish(self):
		self.fd.close()

	def newTemp(self):
		self.tempIdx += 1
		return ".temp%d"%self.tempIdx
